package com.lzq.Injector.methods;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import com.lzq.Injector.CacSqlMethod;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.List;

/**
 * @author pengrx
 */
public class InsertOrUpdateById extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        CacSqlMethod sqlMethod = CacSqlMethod.INSERT_OR_UPDATE_BY_ID;

        String columnScript = SqlScriptUtils.convertTrim(getAllInsertSqlColumn(tableInfo), LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
        String valuesScript = SqlScriptUtils.convertTrim(getAllInsertSqlProperty(tableInfo, null), LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
        String updatesScript = getUpdateScript(tableInfo);

        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript, updatesScript);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource, keyGenerator, null, null);
    }

    /**
     * 获取 insert 时候字段 sql 脚本片段
     * insert into table (字段) values (值)
     * 位于 "字段" 部位, 包含自增的主键字段
     *
     * @param tableInfo
     * @return sql 脚本片段
     */
    private String getAllInsertSqlColumn(TableInfo tableInfo) {
        String result = tableInfo.getAllInsertSqlColumn(true);
        if(tableInfo.getKeyInsertSqlColumn() == EMPTY) {
            result = tableInfo.getKeyColumn() + COMMA + NEWLINE + result;
        }
        return result;
    }

    /**
     * 获取所有 insert 时候插入值 sql 脚本片段
     * insert into table (字段) values (值)
     * 位于 "值" 部位，包含自增的主键字段
     *
     * @return sql 脚本片段
     */
    private String getAllInsertSqlProperty(TableInfo tableInfo, String prefix) {
        String result = tableInfo.getAllInsertSqlProperty(true, prefix);
        if(tableInfo.getKeyInsertSqlProperty(prefix) == EMPTY) {
            final String newPrefix = prefix == null ? EMPTY : prefix;
            result = SqlScriptUtils.safeParam(newPrefix + tableInfo.getKeyProperty()) + COMMA + NEWLINE + result;
        }
        return result;
    }

    /**
     * on duplicate key update set值
     * 位于 "set值" 部位
     * @param tableInfo
     * @return feild=values(feild), feild2=values(feild2)
     */
    private String getUpdateScript(TableInfo tableInfo) {
        StringBuilder builder = new StringBuilder();
        List<TableFieldInfo> list = tableInfo.getFieldList();

        for(int i=0; i<list.size(); i++) {
            builder.append(warper(list.get(i).getColumn(), i == list.size() - 1));
        }
        return builder.toString();
    }

    private String warper(String column, boolean isEnd) {
        if(StringUtils.isNotEmpty(column)) {
            return String.format("%s = values( %s )%s", column, column, isEnd ? "" : ", ");
        }
        return "";
    }
}
